package com.sure0000.basic;

import org.junit.Test;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

/**
 * 反射定义：JAVA反射机制是在运行状态中，对于任意一个类，都能够知道这个类的所有属性和方法；对于任意一个对象，都能够调用它的任意方法和属性；
 * 这种动态获取信息以及动态调用对象方法的功能称为java语言的反射机制。
 *
 * 为什么需要反射？
 * java的反射机制就是增加程序的灵活性，避免将程序写死到代码里,举个例子我们的项目底层有时是用mysql，有时用oracle，需要动态地根据实际情况加载驱动类。
 *
 * @author xuyouchang
 * @date 2020/11/4.
 */
public class ReflectDemo {

    /**
     * 创建对象
     */
    @Test
    public void reflectClass() {
        try {
            Class<?> classBook = Class.forName("com.sure0000.basic.Book");
            Object objectBook = classBook.newInstance();
            Book book = (Book) objectBook;
            book.setName("java abc");
            book.setAuthor("xyc");
            System.out.println("reflectNewInstance book = " + book.toString());
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }

    /**
     * 反射私有的构造方法
     */
    @Test
    public void reflectPrivateConstructor() {
        try {
            Class<?> classBook = Class.forName("com.sure0000.basic.Book");
            Constructor<?> declaredConstructorBook = classBook.getDeclaredConstructor(String.class,String.class);
            declaredConstructorBook.setAccessible(true);
            Object objectBook = declaredConstructorBook.newInstance("Android开发艺术探索","任玉刚");
            Book book = (Book) objectBook;
            System.out.println("reflectPrivateConstructor book = " + book.toString());
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }

    /**
     * 反射私有属性
     */
    @Test
    public void reflectPrivateField() {
        try {
            Class<?> classBook = Class.forName("com.sure0000.basic.Book");
            Object objectBook = classBook.newInstance();
            Field fieldTag = classBook.getDeclaredField("TAG");
            fieldTag.setAccessible(true);
            String tag = (String) fieldTag.get(objectBook);
            System.out.println("reflectPrivateField tag = " + tag);
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }

    /**
     * 反射私有方法
     */
    @Test
    public  void reflectPrivateMethod() {
        try {
            Class<?> classBook = Class.forName("com.android.peter.reflectdemo.Book");
            Method methodBook = classBook.getDeclaredMethod("declaredMethod",int.class);
            methodBook.setAccessible(true);
            Object objectBook = classBook.newInstance();
            String string = (String) methodBook.invoke(objectBook,0);

            System.out.println("reflectPrivateMethod string = " + string);
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }
}
